#ifndef __MAIN_H__
#define __MAIN_H__

#include <glib.h>

#define TOKEN_BRACE_START '['
#define TOKEN_BRACE_END ']'
#define TOKEN_CURLY_START '{'
#define TOKEN_CURLY_END '}'
#define TOKEN_ANGLE_START '<'
#define TOKEN_ANGLE_END '>'
#define TOKEN_MUTEX '|'

typedef enum tree_type {
  TREE_STATIC,
  TREE_DYNAMIC
}TreeType;

typedef struct tree_attr {
  gint index;
  TreeType type;
  GString *expr;
  GSList *head;
  gint map;
  gint point;
}TreeAttr;

// main.c
gint setup_options (int args, char *argv[]);

gint parse_expr (gchar *ip_file);
void parse_expr_each (const GString *expr);
void whole_root_free (GSList **root);

void tree_grow (GSList *root);
void tree_grow_each (gpointer data, gpointer user_data);

void remove_dup (GSList *root);

void harvest_fruit (GSList *root);
GString *pick_up_fruit (GSList *root);

gint report_expr (gchar *op_file, const GString *expr);


// token.c
gboolean is_token_start (gchar ch);
gboolean is_token_end (gchar ch);
gint is_mutex_clean (GString *expr);
gint is_brace_clean (GString *expr);
gint is_curly_clean (GString *expr);
gint is_angle_clean (GString *expr);


// check.c
gint check_expr (gchar *ip_file);
gint check_expr_each (GString *expr);

// tree.c
int parse_tree (GSList **root, const GString *expr);
void find_tree (const GString *expr, gint start_pos, gint *end, gint *type);
GString *get_tree (const GString *expr, gint start, gint end);

// parse.c
gint parse_brace (TreeAttr *attr);
void parse_brace_get_left (GString *expr, gint start, gint *pos);
void parse_brace_get_right (GString *expr, gint start, gint *pos);
gint parse_mutex (TreeAttr *attr);
void parse_mutex_get_left (GString *expr, gint m_pos, gint *pos, gint *first);
void parse_mutex_get_right (GString *expr, gint m_pos, gint *pos, gint *first);
gint parse_curly (TreeAttr *attr);
void parse_curly_get_left (GString *expr, gint start, gint *pos);
void parse_curly_get_right (GString *expr, gint start, gint *pos);
gint parse_angle (TreeAttr *attr);


// debug.c
void debug_print_root (GSList *root);
void debug_print_map (GSList *root);
void log_redirect (const gchar *log_domain, \
                     GLogLevelFlags log_level, \
                     const gchar *message, \
                     gpointer user_data);
void log_dummy_redirect (const gchar *log_domain, \
                        GLogLevelFlags log_level, \
                        const gchar *message, \
                        gpointer user_data);

// angle.c
GString *parse_angle_get_comb_str (GString *str);
GSList *parse_angle_comb_to_list (GString *expr);

// map.c
gint map_mask (GSList *root);
gint map_erase (GSList *root, gint index);
void map_erase_before (GSList *root, gint index);
gint map_init (GSList *root);
gint map_get_pos_at (GSList *root, gint index);
gint map_set_pos_at (GSList *root, gint index);

// clean.c
void basket_strip (GString *expr);

#endif // #define __MAIN_H__
